package com.by.component.importrecord;

import cn.hutool.core.util.BooleanUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.by.component.aliyun.oss.mapper.OssBucketInfoMapper;
import com.by.component.aliyun.oss.properties.AliyunOssProperties;
import com.by.component.importrecord.dto.AddImportRecordSDTO;
import com.by.component.importrecord.dto.InfoImportRecordSDTO;
import com.by.component.importrecord.dto.ItemImportRecord4PageSDTO;
import com.by.component.importrecord.enums.ImportTypeEnum;
import com.by.component.importrecord.mapper.ImportRecordMapper;
import com.by.component.staticresources.dto.ResourceUrlSDTO;
import com.by.component.staticresources.enums.StaticResourcesPlatformTypeEnum;
import com.by.component.staticresources.enums.StaticResourcesTypeEnum;
import com.by.component.staticresources.mapper.StaticResourcesMapper;
import com.by.datasource.transaction.AfterCommitExecutor;
import com.by.datasource.utils.PageUtil;
import com.by.mqsender.support.ByMqSupport;
import com.by.toolkit.consts.LockConst;
import com.by.toolkit.consts.MqTagConst;
import com.by.toolkit.enums.ErrorCodeEnum;
import com.by.toolkit.model.PageReq;
import com.by.toolkit.model.PageResp;
import com.by.toolkit.platform.ByContext;
import com.by.toolkit.utils.SplitterUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.redisson.api.RFuture;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import static com.by.toolkit.utils.ExceptionUtil.nullError;
import static com.by.toolkit.utils.ExceptionUtil.trueError;

@Slf4j
@DubboService
public class ImportServiceImpl implements ImportService {

    @Resource
    private ImportRecordMapper importRecordMapper;

    @Resource
    private ByMqSupport byMqSupport;

    @Resource
    private RedissonClient redisson;

    @Resource
    private StaticResourcesMapper staticResourcesMapper;

    @Override
    public PageResp<ItemImportRecord4PageSDTO> queryPage(PageReq<ItemImportRecord4PageSDTO> req) {
        return PageUtil.toPageResp(importRecordMapper.queryPage(Page.of(req.getPageIdx(), req.getPageSize()), req.getCondition()));
    }

    @Override
    public void addImport(AddImportRecordSDTO dto) {
        Integer importType = dto.getImportType();
        String fileOssUrl = dto.getFileOssUrl();
        Long sysUserId = dto.getSysUserId();

        ImportTypeEnum importTypeEnum = ImportTypeEnum.resolve(importType);
        nullError(importTypeEnum, "导入类型不正确");

        RLock lock = redisson.getLock(SplitterUtil.EN_COLON_JOINER.join(LockConst.IMPORT_LOCK, sysUserId, importType));
        RFuture<Boolean> lockAsync = lock.tryLockAsync(1, 1, TimeUnit.SECONDS);
        try {
            trueError(BooleanUtil.isFalse(lockAsync.join()), ErrorCodeEnum.REDIS_LOCK_FAILED);

            Long unProcessedId = importRecordMapper.unProcessedId(sysUserId, importType);
            trueError(Objects.nonNull(unProcessedId), "有正在处理中的导入记录");

            ImportRecord record = ImportRecord.builder()
                    .importType(importType)
                    .sysUserId(sysUserId)
                    .fileOssUrl(fileOssUrl)
                    .build();
            importRecordMapper.insert(record);

            Long recordId = record.getId();
            AfterCommitExecutor.execute(() -> {
                byMqSupport.sendAsync(Map.of(
                        "recordId", recordId,
                        "importType", importType,
                        "fileOssUrl", fileOssUrl,
                        "sysUserId", sysUserId
                ), MqTagConst.IMPORT);
            });
        } finally {
            lock.unlockAsync();
        }
    }

    @Override
    public void processing(Long recordId) {
        importRecordMapper.processing(recordId);
    }

    @Override
    public void processed(Long recordId, Long importCount, Long successCount, Long errorCount, String fileOssUrl) {
        importRecordMapper.processed(recordId, importCount, successCount, errorCount, fileOssUrl);
    }

    @Override
    public void failProcess(Long recordId, String failMsg) {
        importRecordMapper.failProcess(recordId, failMsg);
    }

    @Override
    public InfoImportRecordSDTO recordInfo(Long recordId) {
        return importRecordMapper.recordInfo(recordId);
    }

    @Override
    public String importTemplateUrl(Integer importType) {
        ImportTypeEnum resolve = ImportTypeEnum.resolve(importType);
        nullError(resolve, "导入类型不正确");

        ResourceUrlSDTO resourceUrl = staticResourcesMapper.generateResourceUrlByProjectId(StaticResourcesPlatformTypeEnum.ALIYUN.getCode()
                , StaticResourcesTypeEnum.FILE.getCode()
                , ByContext.getProjectId());
        log.info("[ImportServiceImpl][importTemplateUrl] importType:[{}] resourceType:[{}] platformType:[{}] resourceUrl:[{}]"
                , importType, StaticResourcesTypeEnum.FILE.getCode(), StaticResourcesPlatformTypeEnum.ALIYUN.getCode(), resourceUrl);
        return SplitterUtil.EN_OBLIQUE_LINE_JOINER.join(StringUtils.defaultIfBlank(resourceUrl.getProjectDomain(), resourceUrl.getCommonDomain())
                , SplitterUtil.EN_OBLIQUE_LINE_JOINER.join("importTemplate", resolve.getDesc() + "-模版.xlsx"));
    }
}
